package com.asura.app.library;

import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.os.StrictMode;
import android.support.multidex.MultiDex;
import android.support.v7.app.AppCompatDelegate;

import com.asura.app.library.initializer.InitializeProcessor;
import com.asura.app.library.initializer.Initializer;
import com.asura.app.library.initializer.LoggerInitializer;
import com.facebook.stetho.Stetho;
import com.orhanobut.logger.Logger;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;

import io.reactivex.plugins.RxJavaPlugins;

/**
 * Created by Asura on 2015/11/28.
 */
public abstract class BaseApplication extends Application {
    private static BaseApplication sInstance;
    private RefWatcher mRefWatcher;

    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    private static Handler sMainHandler;

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (LeakCanary.isInAnalyzerProcess(this)) {
            return;
        }
        if (isDebuggable()) {
            Stetho.initializeWithDefaults(this);
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
        }
        sInstance = this;
        sMainHandler = new Handler();
        mRefWatcher = LeakCanary.install(this);
        InitializeProcessor initializeProcessor = new InitializeProcessor();
        initializeProcessor.registerInitializer(new LoggerInitializer());
        //rxjava 未捕获异常处理
        initializeProcessor.registerInitializer(new Initializer() {
            @Override
            public void initialize(Context context, boolean debuggable) throws Exception {
                RxJavaPlugins.setErrorHandler(throwable -> Logger.e(throwable, throwable.getMessage()));
            }
        });
        registerLibraryInitializer(initializeProcessor);
        initializeProcessor.process(this, isDebuggable());
    }

    public static BaseApplication getInstance() {
        return sInstance;
    }

    public static <T> T getInstance(Class<T> clazz) {
        return clazz.cast(sInstance);
    }

    public RefWatcher getRefWatcher() {
        return mRefWatcher;
    }

    protected abstract void registerLibraryInitializer(InitializeProcessor initializeProcessor);

    protected abstract boolean isDebuggable();

    public abstract ModuleProvider getModuleProvider();

    public static Handler getMainHandler() {
        return sMainHandler;
    }
}
